﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSE.LogPackager.Common;
using PSE.LogPackager.Common.Configuration;
using PSE.Framework.Configuration;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.IO;
using PSE.Framework.ProviderLoader.Configuration;
using PSE.Framework.ProviderLoader;
using PSE.Framework.ErrorLogging;
using PSE.ProcessManager.Common.Configuration;
using System.Net;

namespace PSE.LogPackager.Common.Service
{
    public class LogPackagerServiceClient
    {
        public LogPackagerServiceClient()
        {
        }

        public bool DownloadLicenceFile(string destFile)
        {
            ProviderConfigurationSection configSection = ApplicationConfiguration.GetCurrent().GetSection<ProviderConfigurationSection>("clientProviders");
            ILicenseProvider licenseProvider = null;

            if (configSection != null)
                licenseProvider = ProviderLoader<ILicenseProvider>.LoadProvider(configSection.Providers, "logPackagerLicenseProvider");

            if (licenseProvider != null)
            {
                licenseProvider.DownloadLicenceFile(destFile);

                return true;
            }

            return false;
        }

        public void DownloadSetupFiles(SystemComponent system, Uri sourceAddress, string destPath)
        {
            ApplicationConfiguration applicationConfiguration = PSE.Framework.Configuration.ApplicationConfiguration.GetCurrent();
            LogPackagerConfigurationSection logPackagerConfiguration = applicationConfiguration.GetSection<LogPackagerConfigurationSection>("logPackagerConfiguration");

            Binding binding = logPackagerConfiguration.GetBinding(sourceAddress);

            if (Directory.Exists(destPath))
                Directory.Delete(destPath, true);

            const int bufferSize = 20480;
            byte[] buffer = new byte[bufferSize];
            int bytes = 0;

            using (ChannelFactory<ILogPackagerService> fileTransferProxy = new ChannelFactory<ILogPackagerService>(binding, sourceAddress.ToString()))
            {
                ILogPackagerService client = fileTransferProxy.CreateChannel();

                using (Stream setupFiles = client.DownloadSetupFiles(system))
                {
                    using (MemoryStream writeStream = new MemoryStream())
                    {
                        while ((bytes = setupFiles.Read(buffer, 0, bufferSize)) > 0)
                        {
                            writeStream.Write(buffer, 0, bytes);
                        }

                        writeStream.Position = 0;

                        using (Ionic.Zip.ZipFile zipFile = Ionic.Zip.ZipFile.Read(writeStream))
                        {
                            zipFile.ExtractAll(destPath, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently);
                        }
                    }
                }
            }
        }

        public void WriteClientLog(LogData logData)
        {
            ApplicationConfiguration applicationConfiguration = PSE.Framework.Configuration.ApplicationConfiguration.GetCurrent();

            InteligenceManagerConfigurationSection inteligenceManagerConfiguration = applicationConfiguration.GetSection<InteligenceManagerConfigurationSection>("inteligenceManagerConfiguration");
            LogPackagerConfigurationSection logPackagerConfiguration = applicationConfiguration.GetSection<LogPackagerConfigurationSection>("logPackagerConfiguration");

            // Os logs de client sempre serão gravados no servidor do ProcessManager

            // Captura o nome do host do ProcessManager e substitui no endereço do serviço do LogPackager
            UriBuilder addressBuilder = new UriBuilder(logPackagerConfiguration.GetAddress("Process"));
            addressBuilder.Host = new Uri(inteligenceManagerConfiguration.InteligenceManagerAddress).Host;
            Uri address = addressBuilder.Uri;

            Binding binding = logPackagerConfiguration.GetBinding(address);

            using (ChannelFactory<ILogPackagerService> fileTransferProxy = new ChannelFactory<ILogPackagerService>(binding, address.ToString()))
            {
                ILogPackagerService client = fileTransferProxy.CreateChannel();

                string clientHostName = Dns.GetHostEntry(Dns.GetHostName()).HostName;

                client.WriteClientLog(logData.System, logData.Source, logData.Type, clientHostName, logData.ToXml());
            }
        }
    }
}
